package org.hikari.qqbot.xiuxian.command;

import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * callback抛出的任何异常都会被忽略
 *
 * @author yinchao
 * @version 1.0
 * created at 2024-12-19 15:40:27
 **/
public interface ICommandSendCallback {

    void onSuccess(CommandExecutionInfo command);

    void onError(CommandExecutionInfo command, Throwable e);

    default ICommandSendCallback then(ICommandSendCallback callback) {
        return new CompositeCommandSendCallback(this, callback);
    }

    @Slf4j
    @Getter
    class CompositeCommandSendCallback implements ICommandSendCallback {

        private final Collection<ICommandSendCallback> callbacks;

        public CompositeCommandSendCallback(Collection<ICommandSendCallback> callbacks) {
            List<ICommandSendCallback> list = new ArrayList<>(callbacks.size());
            for (ICommandSendCallback callback : callbacks) {
                if (callback instanceof CompositeCommandSendCallback c) {
                    list.addAll(c.callbacks);
                } else {
                    list.add(callback);
                }
            }
            this.callbacks = list;
        }

        public CompositeCommandSendCallback(ICommandSendCallback... callbacks) {
            this(List.of(callbacks));
        }

        @Override
        public void onSuccess(CommandExecutionInfo command) {
            for (ICommandSendCallback callback : callbacks) {
                try {
                    callback.onSuccess(command);
                } catch (Throwable e) {
                    // pass
                    log.error("Callback process error [{}]", callback.getClass().getName(), e);
                }
            }
        }

        @Override
        public void onError(CommandExecutionInfo command, Throwable ex) {
            for (ICommandSendCallback callback : callbacks) {
                try {
                    callback.onError(command, ex);
                } catch (Throwable e) {
                    // pass
                    log.error("Callback process error [{}]", callback.getClass().getName(), e);
                }
            }
        }

    }

}
